package org.jim.server.demo.service.processor;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.jim.core.ImChannelContext;
import org.jim.core.ImPacket;
import org.jim.core.ImStatus;
import org.jim.core.packets.*;
import org.jim.core.utils.JsonKit;
import org.jim.server.JimServerAPI;
import org.jim.server.command.CommandManager;
import org.jim.server.command.handler.JoinGroupReqHandler;
import org.jim.server.demo.entity.ImGroup;
import org.jim.server.demo.entity.ImUserInfo;
import org.jim.server.demo.service.impl.ImGroupServiceImpl;
import org.jim.server.demo.service.impl.ImUserInfoServiceImpl;
import org.jim.server.processor.group.GroupCmdProcessor;
import org.jim.server.protocol.AbstractProtocolCmdProcessor;
import org.jim.server.req.ImGroupReq;
import org.jim.server.util.ImServerKit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;

import javax.annotation.Resource;
import javax.transaction.Transactional;
import java.util.ArrayList;
import java.util.List;

import static org.jim.core.packets.JoinGroupResult.JOIN_GROUP_RESULT_OK;
import static org.jim.core.packets.JoinGroupResult.JOIN_GROUP_RESULT_UNKNOWN;

/**
 * @author lml
 * 群组处理服务器
 */
@Configuration
public class GroupServiceProcessor extends AbstractProtocolCmdProcessor implements GroupCmdProcessor {

    private static final Logger log = LoggerFactory.getLogger(GroupServiceProcessor.class);

    @Resource
    private ImUserInfoServiceImpl imUserInfoService;

    @Resource
    private ImGroupServiceImpl imGroupService;

    // 群组ID范围（按需调整）
    private static final int MIN_GROUP_ID = 100000;
    private static final int MAX_GROUP_ID = 999999;

    /**
     * 申请加入群组
     */
    @Override
    public JoinGroupRespBody join(Group joinGroup, ImChannelContext imChannelContext) {

        log.info("加入群组处理，群组对象：{}，用户ID为：{}",  joinGroup, imChannelContext.getUserId());

        String userId = imChannelContext.getUserId();

        /**
         * TODO: 判断群组是否存在,群组人数是否达到上限
         */
        if(ObjectUtil.isNull(userId)){
            log.info("加入群组失败，userId为空！");
            return JoinGroupRespBody.failed("加入群组失败，用户ID不存在！");
        }

        QueryWrapper<ImUserInfo> qw = new QueryWrapper<>();
        qw.eq("user_id",userId);
        ImUserInfo imUserInfo = imUserInfoService.getOne(qw);

        if(ObjectUtil.isNull(imUserInfo) || !imUserInfo.getUserState().equals(UserStatusType.ONLINE.getStatus())){
            log.info("加入群组失败，用户不存在或者用户出于离线状态！！");
            return JoinGroupRespBody.failed("加入群组失败，用户不存在或者用户处于离线状态！");
        }

        return JoinGroupRespBody.success(imUserInfo);
    }

    /**
     * 获取某个群组下面的用户成员
     */
    @Override
    public List<User> getUserListByGroup(UserListBody userListBody, ImChannelContext imChannelContext) {


        List<User> list = new ArrayList<>();

        if(ObjectUtil.isNull(userListBody.getGroupId())){
            return list;
        }

        List<User> lists = ImServerKit.getUsersByGroup(userListBody.getGroupId());


        return lists;
    }

    @Override
    public void onFailed(ImChannelContext imChannelContext, GroupCmdProcessor groupCmdProcessor, UserListBody userListBody) {
        log.info("加入群组失败！");
    }

    @Transactional
    @Override
    public void createGroup(RespBody respBody, ImGroupReq imGroupReq, ImChannelContext imChannelContext) {

        log.info("创建群组");

        //check 必要参数
        if(ObjectUtil.isNull(imGroupReq.getGroupId()) || ObjectUtil.isNull(imGroupReq.getUserId())){

            log.info("缺少必要参数，创建群组失败！");

            respBody.setMsg("缺少必要参数，创建群组失败！");

            ImGroup imGroup = new ImGroup();

            BeanUtil.copyProperties(imGroupReq,imGroup);

            Integer groupId = generateGroupId();
            imGroup.setGroupId(groupId);

            if(ObjectUtil.isNull(imGroupReq.getName())){
                imGroup.setName("群聊"+groupId);
            }

            if(ObjectUtil.isNull(imGroupReq.getAvatar())){
                imGroup.setAvatar("https://bpic.588ku.com/element_origin_min_pic/19/04/23/6dd327c08d098230f56d360f39afa1be.jpg");
            }

            if(ObjectUtil.isNull(imGroupReq.getIntroduction())){
                imGroup.setIntroduction("Im 群组，一个有爱的地方！");
            }

            log.info("创建群组信息：{}",imGroup);

            Boolean isSuccess = imGroupService.save(imGroup);

            if(isSuccess){
                log.info("群组创建成功！");
                respBody.setMsg("群组创建成功！");
                respBody.setCode(ImStatus.C10001.getCode());
                respBody.setData(imGroup);

                Group group = new Group();

                BeanUtil.copyProperties(imGroup,group);

                ImPacket groupPacket = new ImPacket(Command.COMMAND_JOIN_GROUP_REQ, JsonKit.toJsonBytes(group));

                imChannelContext.setUserId(String.valueOf(imGroup.getUserId()));
                try {
                    JoinGroupReqHandler joinGroupReqHandler = CommandManager.getCommand(Command.COMMAND_JOIN_GROUP_REQ, JoinGroupReqHandler.class);
                    joinGroupReqHandler.handler(groupPacket, imChannelContext);
                } catch (Exception e) {
                    log.error(e.toString(),e);
                }
            }else{
                log.info("群组创建失败！请稍后尝试!");
                respBody.setMsg("群组创建失败");
            }

        }
    }

    /**
     * 生成群组ID
     */
    private Integer generateGroupId(){

        int groupId;
        do {
            groupId = generateRandomId();
        } while (isGroupIdExists(groupId));

        return groupId;
    }

    /**
     * 生成随机ID（int类型）
     */
    public int generateRandomId() {

        return RandomUtil.randomInt(MIN_GROUP_ID, MAX_GROUP_ID);
    }

    /**
     * 检查群组ID是否已存在
     */
    private boolean isGroupIdExists(int groupId) {

        QueryWrapper<ImGroup> qw = new QueryWrapper<>();
        qw.eq("group_id",groupId);

        ImGroup group  = imGroupService.getOne(qw);

        return ObjectUtil.isNotNull(group);
    }
}
